/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package steg.steki.png;

import javax.swing.JComponent;
import steg.steki.StegException;
import java.io.DataInputStream;
import java.io.EOFException;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.zip.CRC32;
import steg.steki.PlikSteg;
import steg.sekret.Sekret;
import steg.sekret.UnSekret;
import steg.utils.MojaLinkedHashMap;

/**
 * Klasa reprezentująca PNG.
 *
 *
 *  =============== chunks
 *  A chunk consists of four parts: Length (4 bytes),
 *  Chunk type/name (4 bytes),
 *  Chunk data (length bytes) and
 *  CRC (Cyclic Redundancy Code / Checksum, 4 bytes).
 *
 *
 *
 *
 *
 *
 * @author 
 */
public class PlikPNG extends PlikSteg {

// ------------------------------- ZIENNE PRYWATNE -----------------------------
    //-- stałe
    //-- czy
    //-- zmienne
    private PNGDane chunks;

// ------------------------------- ZIENNE PUBLICZNE
    //-- czy
    //-- zmienne

// ------------------------------- KONSTRUKTORY


// ******************************** PUBLICZNE **********************************
// *****************************************************************************
// ------------------------------- FUNKCJE KRYTYCZNE ---------------------------
    public void init(File file) throws StegException, IOException {
        plik = file;
        InputStream in = new FileInputStream(file);
        DataInputStream dataIn = new DataInputStream(in);

        //sprawdzamy nagłówek
        checkNagowek(dataIn);

        //sczytanie chunków
        chunks = readChunks(dataIn);

        long widthLong = chunks.getWidth();
        long heightLong = chunks.getHeight();
        if (widthLong > Integer.MAX_VALUE || heightLong > Integer.MAX_VALUE)
            throw new StegException(new Exception("steg err"), StegException.BLAD_ZLY_FORMAT_PLIKU,"Obraz jest za duży.");
    }

    protected Void doInBackground() {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    protected void done() {
        throw new UnsupportedOperationException("Not supported yet.");
    }


// ------------------------------- FUNKCJE DODATKOWE ---------------------------


    public void generateRandom(int width, int height) {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    public byte[] getPixelArray() throws StegException {
        return chunks.getPixele();
    }


// ******************************** PRYWATNE ***********************************
// *****************************************************************************
// ------------------------------- FUNKCJE KRYTYCZNE
    /**
     * Sczytuje nagłówek który jest dla przydzielony PNG.
     *
     * @param in
     * @throws java.io.IOException
     */
    private static void checkNagowek(DataInputStream in) throws IOException, StegException {
        long nagowek = in.readLong();
        if (nagowek != 0x89504e470d0a1a0aL)
            throw new StegException(new Exception("steg err"), StegException.BLAD_ZLY_FORMAT_PLIKU,"Nagłówek PNG nie został znaleziony!");
    }

    private static PNGDane readChunks(DataInputStream in) throws IOException, StegException {

        PNGDane chunks = new PNGDane();

        boolean czykuniec = true;
        while (czykuniec) {
        try {

            // Pierwsza część czank, to 4 bity, czyli int
            int length = in.readInt();
            if (length < 0)
                throw new StegException(new Exception("steg err"), StegException.BLAD_ZLY_FORMAT_PLIKU,"Chunk jest za długi.");

            // 2 Odczyt typu
            byte[] typ = new byte[4];
            in.readFully(typ);

            // 3 część chunku, dane
            byte[] dane = new byte[length];
            in.readFully(dane);

            // 4 Sprawzenie CRC.
            long crc = in.readInt() & 0x00000000ffffffffL; // sprawdzenie znaku, bez znaku
            if (verifyCRC(typ, dane, crc) == false)
                throw new StegException(new Exception("steg err"), StegException.BLAD_ZLY_FORMAT_PLIKU,"Plik jest uszkodzony.");

            PNGChunk chunk = new PNGChunk(typ, dane);
            chunks.add(chunk);
        } catch (EOFException eofe) {
            //the ned
            czykuniec = false;
        }
        }
        return chunks;
    }

    /**
     * Obliczenie sumy kontrolnej CRC32.
     * używana w PNG
     * @param rodzaj
     * @param dane
     * @param crc
     * @return
     */
    private static boolean verifyCRC(byte[] rodzaj, byte[] dane, long crc) {
        CRC32 crc32 = new CRC32();
        crc32.update(rodzaj);
        crc32.update(dane);
        long calculated = crc32.getValue();
        return (calculated == crc);
    }
// ------------------------------- FUNKCJE POMOCNICZE
    public MojaLinkedHashMap getMetaDane() {
        //throw new UnsupportedOperationException("Not supported yet.");
        
        MojaLinkedHashMap map = new MojaLinkedHashMap();

        map.put("Nazwa", plik.getName() );
        map.put("Rozmiar", plik.length() );
        map.put("Tag", "PNG" );
        map.put("Chunks", chunks.getChunksNumber()  );

        return map;
    }


// ------------------------------- FUNKCJE CZY ---------------------------------

    public long getPojemnosc() {
        throw new UnsupportedOperationException("Not supported yet.");
    }



    // DOKASCACJII !
    @Deprecated
    public void unsteg(File fileIn, UnSekret paczka) throws StegException, IOException {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public void stegProcess() throws StegException {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    public void unsteg(UnSekret paczka) throws StegException, IOException {
        throw new UnsupportedOperationException("Not supported yet.");
    }

}
